import React, {useCallback, useRef, useState} from "react";
import {VJsonComponent} from "../../factory";
import {DataComponentProp, DataComponentState, VJsonDataComponentBase} from "../../datasource";
import {Table as AntTable} from "antd";
import {DndProvider, useDrag, useDrop, createDndContext} from 'react-dnd';
import {HTML5Backend} from 'react-dnd-html5-backend';

import _ from "lodash";
import {toJS} from "mobx";

export interface SortableTableVJsonDataProp extends DataComponentProp<SortableTable> {
    /**
     * 是否可见
     */
    visible?: boolean
    columns: any[]
}

export interface SortableTableState extends DataComponentState {
}

@VJsonComponent({
    view: 'sortableTable'
})
export default class SortableTable extends VJsonDataComponentBase<SortableTable, SortableTableVJsonDataProp, SortableTableState> {
    static defaultProps = {
        ...VJsonDataComponentBase.defaultProps,
        visible: true,
        data: []
    }

    constructor(props: any) {
        super(props);

        _.defaults(
            props.vjson,
            SortableTable.defaultProps
        )
    }

    moveRow(dragIndex: number, hoverIndex: number) {
        const {data} = this;
        const dragRow = data![dragIndex];
        data.splice(dragIndex, 1);
        data.splice(hoverIndex, 0, dragRow);
    };


    render() {
        if (!this.props.vjson.visible) {
            return null
        }

        const me = this;
        const DragSortingTable = () => {

            const components = {
                body: {
                    row: DragableBodyRow,
                },
            };

            const manager = useRef(RNDContext);

            return (
                <DndProvider manager={manager!.current.dragDropManager!}>
                    <AntTable
                        columns={me.props.vjson.columns}
                        dataSource={me.data}
                        components={components}
                        // @ts-ignore
                        onRow={(record: number, index: number) => ({
                            index,
                            moveRow: me.moveRow.bind(me),
                        })}
                    />
                </DndProvider>
            );
        };

        return (
            <DragSortingTable/>
        )
    }
}


const RNDContext = createDndContext(HTML5Backend);

const type = 'DragableBodyRow';

// @ts-ignore
const DragableBodyRow = ({index, moveRow, className, style, ...restProps}) => {
    const ref = React.useRef();
    const [{isOver, dropClassName}, drop] = useDrop({
        accept: type,
        collect: monitor => {
            const {index: dragIndex} = monitor.getItem() || {};
            if (dragIndex === index) {
                return {};
            }
            return {
                isOver: monitor.isOver(),
                dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
            };
        },
        drop: (item: any) => {
            moveRow(item.index, index);
        },
    });
    const [, drag] = useDrag({
        item: {type, index},
        collect: monitor => ({
            isDragging: monitor.isDragging(),
        }),
    });
    drop(drag(ref));
    return (
        <tr
            // @ts-ignore
            ref={ref}
            className={`${className}${isOver ? dropClassName : ''}`}
            style={{cursor: 'move', ...style}}
            {...restProps}
        />
    );
};

// @ts-ignore
